#!/usr/bin/env python
# -*- coding: utf-8 -*-

import datetime

import wx
import wx.lib.buttons as buttons
import wx.html
from wx.lib.masked import TimeCtrl

locale = wx.Locale()
locale.Init2()

from gcal import GCalHandler, BadAuthentication, RequestError, gaierror

CONFIGFILE = 'gcaltrack.cfg'


class GCTMainFrame(wx.Frame):
    """
    sudo apt-get install python-wxgtk2.8
    sudo easy_install http://gdata-python-client.googlecode.com/files/gdata-2.0.2.tar.gz
    """

    def __init__(self, *args, **kwds):

        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)

        # Menu Bar
        self.main_frame_menubar = wx.MenuBar()
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(100, _("&About"), "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(105, _("&Quit"), "", wx.ITEM_NORMAL)
        self.main_frame_menubar.Append(wxglade_tmp_menu, _("&File"))

        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(200, _("&Today"), "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.Append(205, _("&Weekly"), "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.Append(210, _("&Monthly"), "", wx.ITEM_NORMAL)
        wxglade_tmp_menu.Append(215, _("&Custom"), "", wx.ITEM_NORMAL)
        self.main_frame_menubar.Append(wxglade_tmp_menu, _("&Report"))

        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(300, _("&Configure"), "", wx.ITEM_NORMAL)
        self.main_frame_menubar.Append(wxglade_tmp_menu, _("&Options"))
        self.SetMenuBar(self.main_frame_menubar)

        self.main_frame_statusbar = self.CreateStatusBar(1, 0)
        self.calendar_choice = wx.ComboBox(self, -1, choices=[], style=wx.CB_DROPDOWN)
        self.short_description = wx.TextCtrl(self, -1, "")
        self.long_description = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)

        bmp = wx.Image("stop-watch-green_icon.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap()
        self.run_stop = buttons.GenBitmapTextToggleButton(self, 10, bmp, _("Run"))
        bmp = wx.Image("stop-watch-red_icon.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap()
        self.run_stop.SetBitmapSelected(bmp)

        bmp = wx.Image("task.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap()
        self.send = buttons.GenBitmapTextToggleButton(self, 20, bmp, _("Send"))

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_MENU, self.OnAbout, id=100)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=105)
        self.Bind(wx.EVT_MENU, self.OnReportToday, id=200)
        self.Bind(wx.EVT_MENU, self.OnReportWeekly, id=205)
        self.Bind(wx.EVT_MENU, self.OnReportMonthly, id=210)
        self.Bind(wx.EVT_MENU, self.OnReportCustom, id=215)
        self.Bind(wx.EVT_MENU, self.OnConfigure, id=300)
        self.Bind(wx.EVT_COMBOBOX, self.OnCalendarSelect, self.calendar_choice)

        self.Bind(wx.EVT_BUTTON, self.ToggleRun, self.run_stop)

        self.Bind(wx.EVT_BUTTON, self.OnSend, self.send)

        self.timer = wx.Timer(self, 1)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)

        self.cfg = wx.Config(CONFIGFILE)
        try:
            self.logingcal()
        except gaierror:
            wx.MessageBox(_("Can't connect to internet"), _("check internet"), wx.ICON_ERROR)
        except BadAuthentication:
            dlg = wx.MessageBox(_('Check your login info in options configure.'), _('Login Info'), wx.ICON_ERROR)
        self.running = False

    def logingcal(self):
        self.login = self.cfg.Read('login')
        self.passwd = self.cfg.Read('passwd')
        self.current_cal_index = self.cfg.ReadInt('cal_index', 0)
        self.workday_length = self.cfg.Read('workday_length', '08:30')

        self.calendar_handler = GCalHandler(self.login, self.passwd)
        self.calendar_infos = self.calendar_handler.getOwnCalendars()
        self.current_cal_id = self.calendar_infos['ids'][self.current_cal_index]

        self.calendar_choice.AppendItems(self.calendar_infos['titles'])
        self.calendar_choice.SetSelection(self.current_cal_index)
        self.run_stop.Enable()

    def __set_properties(self):
        self.SetTitle(_("gcaltrack"))
        self.SetSize((273, 256))
        self.main_frame_statusbar.SetFieldsCount(2)
        self.main_frame_statusbar.SetStatusWidths([-1, -2])
        # statusbar fields
        main_frame_statusbar_fields = [_("stopped"), "00:00:00"]
        for i in range(len(main_frame_statusbar_fields)):
            self.main_frame_statusbar.SetStatusText(main_frame_statusbar_fields[i], i)
        # end wxGlade
        favicon = wx.Icon('task.gif', wx.BITMAP_TYPE_GIF, 16, 16)
        wx.Frame.SetIcon(self, favicon)
        self.send.Disable()
        self.run_stop.Disable()

    def __do_layout(self):
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_2 = wx.FlexGridSizer(1, 2, 0, 0)
        sizer_1.Add(self.calendar_choice, 0, wx.EXPAND | wx.ADJUST_MINSIZE, 0)
        sizer_1.Add(self.short_description, 0, wx.TOP | wx.EXPAND, 5)
        sizer_1.Add(self.long_description, 1, wx.TOP | wx.BOTTOM | wx.EXPAND, 5)
        sizer_2.Add(self.run_stop, 0, wx.RIGHT | wx.ADJUST_MINSIZE, 10)
        sizer_2.Add(self.send, 0, wx.RIGHT | wx.ADJUST_MINSIZE, 10)
        sizer_1.Add(sizer_2, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 2)
        self.SetSizer(sizer_1)
        self.Layout()

    def OnAbout(self, event):
        dlg = AboutDialog(self)
        dlg.ShowModal()
        dlg.Destroy()

    def OnQuit(self, event):
        self.Close()
        return True

    def OnReportToday(self, event):
        self.report = self.calendar_handler.DayQuery(self.current_cal_id, self.workday_length)
        dlg = Report(self)
        dlg.ShowModal()
        dlg.Destroy()

    def OnReportWeekly(self, event):
        self.report = self.calendar_handler.WeekQuery(self.current_cal_id, self.workday_length)
        dlg = Report(self)
        dlg.ShowModal()
        dlg.Destroy()

    def OnReportMonthly(self, event):
        self.report = self.calendar_handler.MonthQuery(self.current_cal_id, self.workday_length)
        dlg = Report(self)
        dlg.ShowModal()
        dlg.Destroy()

    def OnReportCustom(self, event):
        dlg = CustomReportDialog(self)
        if dlg.ShowModal() == wx.ID_OK:
            self.report = self.calendar_handler.CustomQuery(self.current_cal_id,
                                              dlg.start_date.GetValue(),
                                              dlg.end_date.GetValue(), self.workday_length)
            dlgreport = Report(self)
            dlgreport.ShowModal()
            dlgreport.Destroy()
        dlg.Destroy()

    def OnConfigure(self, event):
        dlg = ConfigDialog(self)
        if dlg.ShowModal() == wx.ID_OK:
            self.cfg.Write('login', dlg.login.GetValue())
            self.cfg.Write('passwd', dlg.passwd.GetValue())
            self.cfg.Write('workday_length', dlg.workday_length.GetValue())
            self.cfg.Flush()
            self.logingcal()
        dlg.Destroy()

    def ToggleRun(self, event):
        if not self.running:
            self.running = True
            self.main_frame_statusbar.SetStatusText(_("running"), 0)
            self.starttime = datetime.datetime.utcnow()
            self.timer.Start(1000)
            self.run_stop.SetLabel(_('&Stop'))
            self.send.Disable()
        else:
            self.running = False
            self.main_frame_statusbar.SetStatusText(_("stopped"), 0)
            self.endtime = datetime.datetime.utcnow()
            self.timer.Stop()
            self.run_stop.SetLabel(_('&Run'))
            self.SetTitle(_("gcaltrack"))
            self.send.Enable()

    def OnTimer(self, event):
        currentime = datetime.datetime.utcnow()
        duration = currentime - self.starttime
        min = duration.seconds / 60
        sec = ('%d' % (duration.seconds % 60)).zfill(2)
        h = ('%d' % (min / 60)).zfill(2)
        m = ('%d' % (min % 60)).zfill(2)
        status_text = "%s:%s:%s" % (h, m, sec)
        self.SetTitle('%s %s' % (_("gcaltrack"), status_text))
        self.main_frame_statusbar.SetStatusText(status_text, 1)

    def OnSend(self, event):
        title = self.short_description.GetValue()
        content = self.long_description.GetValue()
        try:
            self.calendar_handler.InsertSingleEvent(self.current_cal_id, self.starttime, self.endtime,
                                                 title=title, content=content)
        except RequestError:
            wx.MessageBox(_("Error while inserting event in google calendar"), _("Error"))

    def OnCalendarSelect(self, event):
        index = event.GetSelection()
        try:
            self.current_cal_id = self.calendar_infos['ids'][index]
            self.cfg.WriteInt('cal_index', index)
        except AttributeError: #no connection
            pass


class AboutDialog(wx.Dialog):
    """ probablement a virer pour une forme + simple
    """

    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
        wx.Dialog.__init__(self, *args, **kwds)
        self.about_text = wx.StaticText(self, -1, _("\nGCalTrack allows to track time spent\non activities to a Google Calendar\n\nv 0.3"))
        self.button_1 = wx.Button(self, wx.ID_CLOSE, "")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.OnClose, self.button_1)

    def __set_properties(self):
        self.SetTitle(_("about"))

    def __do_layout(self):
        sizer_3 = wx.BoxSizer(wx.VERTICAL)
        sizer_3.Add(self.about_text, 1, wx.BOTTOM | wx.EXPAND, 10)
        sizer_3.Add(self.button_1, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ADJUST_MINSIZE, 0)
        self.SetSizer(sizer_3)
        sizer_3.Fit(self)
        self.Layout()

    def OnClose(self, event): # wxGlade: AboutDialog.<event_handler>
        self.Close()


class CustomReportDialog(wx.Dialog):

    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Dialog.__init__(self, *args, **kwds)
        self.start_label = wx.StaticText(self, -1, _("Start date :"))
        self.start_date = wx.DatePickerCtrl(self, -1, wx.DateTime_Now())
        self.end_label = wx.StaticText(self, -1, _("End Date :"))
        self.end_date = wx.DatePickerCtrl(self, -1, wx.DateTime_Now())
        self.button_3 = wx.Button(self, wx.ID_OK, "")
        self.button_4 = wx.Button(self, wx.ID_CANCEL, "")
        self.__set_properties()
        self.__do_layout()

    def __set_properties(self):
        self.SetTitle(_("Choose dates"))
        self.SetSize((229, 165))

    def __do_layout(self):
        grid_sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_4 = wx.GridSizer(1, 2, 0, 0)
        grid_sizer_1.Add(self.start_label, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 5)
        grid_sizer_1.Add(self.start_date, 0, wx.BOTTOM | wx.EXPAND, 10)
        grid_sizer_1.Add(self.end_label, 0, wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 5)
        grid_sizer_1.Add(self.end_date, 0, wx.BOTTOM | wx.EXPAND, 10)
        sizer_4.Add(self.button_3, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0)
        sizer_4.Add(self.button_4, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0)
        grid_sizer_1.Add(sizer_4, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 0)
        self.SetSizer(grid_sizer_1)
        self.Layout()


class Report(wx.Dialog):

    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Dialog.__init__(self, *args, **kwds)
        parent = self.GetParent()

        # create the controls
        self.report = wx.TextCtrl(self, -1, parent.report, style=wx.TE_MULTILINE | wx.HSCROLL)
        self.button_copy = wx.Button(self, 20, _("Copy to clipboard"))
        self.button_ok = wx.Button(self, wx.ID_OK, "")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.OnCopy, self.button_copy)
        self.Bind(wx.EVT_BUTTON, self.OnClose, self.button_ok)

    def __set_properties(self):
        self.SetTitle(_("Report"))
        self.SetSize((445, 480))

    def __do_layout(self):
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_2 = wx.FlexGridSizer(1, 2, 0, 0)
        sizer_1.Add(self.report, 1, wx.EXPAND, 5)
        sizer_2.Add(self.button_copy, 0, wx.RIGHT | wx.ADJUST_MINSIZE, 10)
        sizer_2.Add(self.button_ok, 0, wx.RIGHT | wx.ADJUST_MINSIZE, 10)
        sizer_1.Add(sizer_2, 0, wx.TOP | wx.ALIGN_CENTER_HORIZONTAL | wx.ADJUST_MINSIZE, 5)
        self.SetSizer(sizer_1)
        self.Layout()

    def OnCopy(self, event):
        data = wx.TextDataObject()
        data.SetText(self.report.GetValue())
        if wx.TheClipboard.Open():
            wx.TheClipboard.SetData(data)
            wx.TheClipboard.Close()
        else:
            wx.MessageBox(_("Unable to open the clipboard"), _("Error"))

    def OnClose(self, event):
        self.Close()


class ConfigDialog(wx.Dialog):

    def __init__(self, *args, **kwds):
        # begin wxGlade: ConfigDialog.__init__
        wx.Dialog.__init__(self, *args, **kwds)

        self.login_label = wx.StaticText(self, -1, _("Login :"))
        self.login = wx.TextCtrl(self, -1, "")

        self.passwd_label = wx.StaticText(self, -1, _("Password :"))
        self.passwd = wx.TextCtrl(self, -1, "", style=wx.TE_PASSWORD)

        self.workday_length_label = wx.StaticText(self, -1, _("Default working hours in a full day:"))
        self.workday_length_spin = wx.SpinButton(self, -1)
        self.workday_length = TimeCtrl(self, -1, value='08:30:00', format='24HHMM', spinButton=self.workday_length_spin)

        self.button_ok = wx.Button(self, wx.ID_OK, "")
        self.button_cancel = wx.Button(self, wx.ID_CANCEL, "")

        self.__set_properties()
        self.__do_layout()

        # end wxGlade
        parent = self.GetParent()
        self.login.SetValue(parent.login)
        self.passwd.SetValue(parent.passwd)
        self.workday_length.SetValue(parent.workday_length)

    def __set_properties(self):
        self.SetTitle(_("Configure"))
        self.SetSize((229, 230))

    def __do_layout(self):
        grid_sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_length = wx.GridSizer(1, 2, 10, 0)
        sizer_buttons = wx.GridSizer(1, 2, 15, 5)

        # login
        grid_sizer_1.Add(self.login_label, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 5)
        grid_sizer_1.Add(self.login, 0, wx.BOTTOM | wx.EXPAND, 10)
        # passwd
        grid_sizer_1.Add(self.passwd_label, 0, wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 5)
        grid_sizer_1.Add(self.passwd, 0, wx.BOTTOM | wx.EXPAND, 10)

        # day length
        grid_sizer_1.Add(self.workday_length_label, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 5)
        sizer_length.Add(self.workday_length, 0, wx.RIGHT, 0)
        sizer_length.Add(self.workday_length_spin, 0, wx.LEFT, 0)
        grid_sizer_1.Add(sizer_length, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM, 10)

        sizer_buttons.Add(self.button_ok, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0)
        sizer_buttons.Add(self.button_cancel, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0)

        grid_sizer_1.Add(sizer_buttons, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 40)
        self.SetSizer(grid_sizer_1)
        self.Layout()


class GCalTrackApp(wx.App):

    def OnInit(self):
        wx.InitAllImageHandlers()
        main_frame = GCTMainFrame(None, -1, "")
        self.SetTopWindow(main_frame)
        main_frame.Show()
        return 1

if __name__ == "__main__":
    import gettext
    gettext.install("app") # replace with the appropriate catalog name

    app = GCalTrackApp(0)
    app.MainLoop()
